package net.gdface.bean.openbeans.factory;

import static net.gdface.annotations.ActiveOnClassSupport.createInstanceIfActiveClassPresent;
import static net.gdface.annotations.ActiveOnClassSupport.getActiveOnClass;
import static net.gdface.annotations.ActiveOnClassSupport.isActive;

import com.googlecode.openbeans.IntrospectionException;
import com.googlecode.openbeans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.google.common.collect.ImmutableList;

import net.gdface.annotations.ActiveOnClass;

/**
 * {@link PropertyDescriptorFactory}对象管理
 * @author guyadong
 * @since 2.7.0
 *
 */
public class PropertyDescriptorFactories implements PropertyDescriptorFactory{
	private final List<PropertyDescriptorFactory> builtinDescriptorFactorys;
	private final List<PropertyDescriptorFactory> nostandardDescriptorFactorys = new ArrayList<>();
	public PropertyDescriptorFactories() {
		builtinDescriptorFactorys  = ImmutableList.<PropertyDescriptorFactory>of(
						new MapDescriptorFactory(),
						new FieldDescriptorFactory());
		for(Class<? extends PropertyDescriptorFactory> clazz:Arrays.asList(UnnameRowDescriptorFactory.class,BaseRowDescriptorFactory.class)){
			PropertyDescriptorFactory instance = createInstanceIfActiveClassPresent(clazz);
			if(null != instance){
				nostandardDescriptorFactorys.add(instance);
			}
		}
	}
	public void addFirst(PropertyDescriptorFactory element) {
		if(null != element){
			synchronized (this) {
				builtinDescriptorFactorys.add(0, element);
			}
		}
	}
	public void add(PropertyDescriptorFactory element) {
		if(null != element){
			synchronized (this) {
				builtinDescriptorFactorys.add(element);
			}
		}
	}
	@Override
	public PropertyDescriptor descriptorOf(Object bean, String name) throws IntrospectionException{
		PropertyDescriptor descriptor = nostandardDescriptorOf(bean,name);
		if(null != descriptor){
			return descriptor;
		}
		return builtinDescriptorOf(bean,name);
	}
	/**
	 * 从非标准{@link PropertyDescriptorFactory}中返回{@code bean}中{@code name}指定字段的{@link PropertyDescriptor}实例,没有则返回{@code null}
	 * @param bean
	 * @param name
	 * @throws IntrospectionException
	 * @since 2.7.4
	 */
	public PropertyDescriptor nostandardDescriptorOf(Object bean, String name) throws IntrospectionException{
		PropertyDescriptor descriptor;
		for(PropertyDescriptorFactory factory:nostandardDescriptorFactorys){
			if(isActive(factory.getClass(),bean)){
				descriptor =  factory.descriptorOf(bean, name);
				if(null != descriptor){
					return descriptor;
				}
			}
		}
		return null;
	}
	/**
	 * 从内置{@link PropertyDescriptorFactory}中返回{@code bean}中{@code name}指定字段的{@link PropertyDescriptor}实例,没有则返回{@code null}
	 * @param bean
	 * @param name
	 * @throws IntrospectionException
	 * @since 2.7.4
	 */
	public PropertyDescriptor builtinDescriptorOf(Object bean, String name) throws IntrospectionException{
		PropertyDescriptor descriptor;
		for(PropertyDescriptorFactory factory:builtinDescriptorFactorys){
			if(isActive(factory.getClass(),bean)){
				descriptor =  factory.descriptorOf(bean, name);
				if(null != descriptor){
					return descriptor;
				}
			}
		}
		return null;
	}
}
